package com.yjl.hotel.customview;

import com.yjl.hotel.R;

import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

public class SlidingSwitcherView extends RelativeLayout implements OnTouchListener {

	/**
	 * 璁╄彍鍗曟粴鍔紝鎵嬫寚婊戝姩闇�瑕佽揪鍒扮殑閫熷害銆�
	 */
	public static final int SNAP_VELOCITY = 200;

	/**
	 * SlidingSwitcherView鐨勫搴︺��
	 */
	private int switcherViewWidth;

	/**
	 * 褰撳墠鏄剧ず鐨勫厓绱犵殑涓嬫爣銆�
	 */
	private int currentItemIndex;

	/**
	 * 鑿滃崟涓寘鍚殑鍏冪礌鎬绘暟銆�
	 */
	private int itemsCount;

	/**
	 * 鍚勪釜鍏冪礌鐨勫亸绉昏竟鐣屽�笺��
	 */
	private int[] borders;

	/**
	 * 鏈�澶氬彲浠ユ粦鍔ㄥ埌鐨勫乏杈圭紭銆傚�肩敱鑿滃崟涓寘鍚殑鍏冪礌鎬绘暟鏉ュ畾锛宮arginLeft鍒拌揪姝ゅ�间箣鍚庯紝涓嶈兘鍐嶅噺灏戙��
	 * 
	 */
	private int leftEdge = 0;

	/**
	 * 鏈�澶氬彲浠ユ粦鍔ㄥ埌鐨勫彸杈圭紭銆傚�兼亽涓�0锛宮arginLeft鍒拌揪姝ゅ�间箣鍚庯紝涓嶈兘鍐嶅鍔犮��
	 */
	private int rightEdge = 0;

	/**
	 * 璁板綍鎵嬫寚鎸変笅鏃剁殑妯潗鏍囥��
	 */
	private float xDown;

	/**
	 * 璁板綍鎵嬫寚绉诲姩鏃剁殑妯潗鏍囥��
	 */
	private float xMove;

	/**
	 * 璁板綍鎵嬫満鎶捣鏃剁殑妯潗鏍囥��
	 */
	private float xUp;

	/**
	 * 鑿滃崟甯冨眬銆�
	 */
	private LinearLayout itemsLayout;

	/**
	 * 鏍囩甯冨眬銆�
	 */
	private LinearLayout dotsLayout;

	/**
	 * 鑿滃崟涓殑绗竴涓厓绱犮��
	 */
	private View firstItem;

	/**
	 * 鑿滃崟涓涓�涓厓绱犵殑甯冨眬锛岀敤浜庢敼鍙榣eftMargin鐨勫�硷紝鏉ュ喅瀹氬綋鍓嶆樉绀虹殑鍝竴涓厓绱犮��
	 */
	private MarginLayoutParams firstItemParams;

	/**
	 * 鐢ㄤ簬璁＄畻鎵嬫寚婊戝姩鐨勯�熷害銆�
	 */
	private VelocityTracker mVelocityTracker;

	/**
	 * 閲嶅啓SlidingSwitcherView鐨勬瀯閫犲嚱鏁帮紝鐢ㄤ簬鍏佽鍦╔ML涓紩鐢ㄥ綋鍓嶇殑鑷畾涔夊竷灞�銆�
	 * 
	 * @param context
	 * @param attrs
	 */
	public SlidingSwitcherView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	/**
	 * 婊氬姩鍒颁笅涓�涓厓绱犮��
	 */
	public void scrollToNext() {
		new ScrollTask().execute(-20);
	}

	/**
	 * 婊氬姩鍒颁笂涓�涓厓绱犮��
	 */
	public void scrollToPrevious() {
		new ScrollTask().execute(20);
	}

	/**
	 * 鍦╫nLayout涓噸鏂拌瀹氳彍鍗曞厓绱犲拰鏍囩鍏冪礌鐨勫弬鏁般��
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (changed) {
			initializeItems();
			initializeDots();
		}
	}

	/**
	 * 鍒濆鍖栬彍鍗曞厓绱狅紝涓烘瘡涓�涓瓙鍏冪礌澧炲姞鐩戝惉浜嬩欢锛屽苟涓旀敼鍙樻墍鏈夊瓙鍏冪礌鐨勫搴︼紝璁╁畠浠瓑浜庣埗鍏冪礌鐨勫搴︺��
	 */
	private void initializeItems() {
		switcherViewWidth = getWidth();
		itemsLayout = (LinearLayout) getChildAt(0);
		itemsCount = itemsLayout.getChildCount();
		borders = new int[itemsCount];
		for (int i = 0; i < itemsCount; i++) {
			borders[i] = -i * switcherViewWidth;
			View item = itemsLayout.getChildAt(i);
			MarginLayoutParams params = (MarginLayoutParams) item.getLayoutParams();
			params.width = switcherViewWidth;
			item.setLayoutParams(params);
			item.setOnTouchListener(this);
		}
		leftEdge = borders[itemsCount - 1];
		firstItem = itemsLayout.getChildAt(0);
		firstItemParams = (MarginLayoutParams) firstItem.getLayoutParams();
	}

	/**
	 * 鍒濆鍖栨爣绛惧厓绱犮��
	 */
	private void initializeDots() {
		dotsLayout = (LinearLayout) getChildAt(1);
		refreshDotsLayout();
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		Log.d("TAG", "on touch event");
		createVelocityTracker(event);
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// 鎵嬫寚鎸変笅鏃讹紝璁板綍鎸変笅鏃剁殑妯潗鏍�
			xDown = event.getRawX();
			break;
		case MotionEvent.ACTION_MOVE:
			Log.d("TAG", "action move");
			// 鎵嬫寚绉诲姩鏃讹紝瀵规瘮鎸変笅鏃剁殑妯潗鏍囷紝璁＄畻鍑虹Щ鍔ㄧ殑璺濈锛屾潵璋冩暣宸︿晶甯冨眬鐨刲eftMargin鍊硷紝浠庤�屾樉绀哄拰闅愯棌宸︿晶甯冨眬
			xMove = event.getRawX();
			int distanceX = (int) (xMove - xDown) - (currentItemIndex * switcherViewWidth);
			firstItemParams.leftMargin = distanceX;
			Log.d("TAG", "left margin is " + firstItemParams.leftMargin);
			if (beAbleToScroll()) {
				firstItem.setLayoutParams(firstItemParams);
			}
			break;
		case MotionEvent.ACTION_UP:
			// 鎵嬫寚鎶捣鏃讹紝杩涜鍒ゆ柇褰撳墠鎵嬪娍鐨勬剰鍥撅紝浠庤�屽喅瀹氭槸婊氬姩鍒板乏渚у竷灞�锛岃繕鏄粴鍔ㄥ埌鍙充晶甯冨眬
			xUp = event.getRawX();
			if (beAbleToScroll()) {
				if (wantScrollToPrevious()) {
					if (shouldScrollToPrevious()) {
						currentItemIndex--;
						scrollToPrevious();
						refreshDotsLayout();
					} else {
						scrollToNext();
					}
				} else if (wantScrollToNext()) {
					if (shouldScrollToNext()) {
						currentItemIndex++;
						scrollToNext();
						refreshDotsLayout();
					} else {
						scrollToPrevious();
					}
				}
			}
			recycleVelocityTracker();
			break;
		}
		return false;
	}

	/**
	 * 褰撳墠鏄惁鑳藉婊氬姩锛屾粴鍔ㄥ埌绗竴涓垨鏈�鍚庝竴涓厓绱犳椂灏嗕笉鑳藉啀婊氬姩銆�
	 * 
	 * @return 褰撳墠leftMargin鐨勫�煎湪leftEdge鍜宺ightEdge涔嬮棿杩斿洖true,鍚﹀垯杩斿洖false銆�
	 */
	private boolean beAbleToScroll() {
		return firstItemParams.leftMargin < rightEdge && firstItemParams.leftMargin > leftEdge;
	}

	/**
	 * 鍒ゆ柇褰撳墠鎵嬪娍鐨勬剰鍥炬槸涓嶆槸鎯虫粴鍔ㄥ埌涓婁竴涓彍鍗曞厓绱犮�傚鏋滄墜鎸囩Щ鍔ㄧ殑璺濈鏄鏁帮紝鍒欒涓哄綋鍓嶆墜鍔挎槸鎯宠婊氬姩鍒颁笂涓�涓彍鍗曞厓绱犮��
	 * 
	 * @return 褰撳墠鎵嬪娍鎯虫粴鍔ㄥ埌涓婁竴涓彍鍗曞厓绱犺繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse銆�
	 */
	private boolean wantScrollToPrevious() {
		return xUp - xDown > 0;
	}

	/**
	 * 鍒ゆ柇褰撳墠鎵嬪娍鐨勬剰鍥炬槸涓嶆槸鎯虫粴鍔ㄥ埌涓嬩竴涓彍鍗曞厓绱犮�傚鏋滄墜鎸囩Щ鍔ㄧ殑璺濈鏄礋鏁帮紝鍒欒涓哄綋鍓嶆墜鍔挎槸鎯宠婊氬姩鍒颁笅涓�涓彍鍗曞厓绱犮��
	 * 
	 * @return 褰撳墠鎵嬪娍鎯虫粴鍔ㄥ埌涓嬩竴涓彍鍗曞厓绱犺繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse銆�
	 */
	private boolean wantScrollToNext() {
		return xUp - xDown < 0;
	}

	/**
	 * 鍒ゆ柇鏄惁搴旇婊氬姩鍒颁笅涓�涓彍鍗曞厓绱犮�傚鏋滄墜鎸囩Щ鍔ㄨ窛绂诲ぇ浜庡睆骞曠殑1/2锛屾垨鑰呮墜鎸囩Щ鍔ㄩ�熷害澶т簬SNAP_VELOCITY锛�
	 * 灏辫涓哄簲璇ユ粴鍔ㄥ埌涓嬩竴涓彍鍗曞厓绱犮��
	 * 
	 * @return 濡傛灉搴旇婊氬姩鍒颁笅涓�涓彍鍗曞厓绱犺繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse銆�
	 */
	private boolean shouldScrollToNext() {
		return xDown - xUp > switcherViewWidth / 2 || getScrollVelocity() > SNAP_VELOCITY;
	}

	/**
	 * 鍒ゆ柇鏄惁搴旇婊氬姩鍒颁笂涓�涓彍鍗曞厓绱犮�傚鏋滄墜鎸囩Щ鍔ㄨ窛绂诲ぇ浜庡睆骞曠殑1/2锛屾垨鑰呮墜鎸囩Щ鍔ㄩ�熷害澶т簬SNAP_VELOCITY锛�
	 * 灏辫涓哄簲璇ユ粴鍔ㄥ埌涓婁竴涓彍鍗曞厓绱犮��
	 * 
	 * @return 濡傛灉搴旇婊氬姩鍒颁笂涓�涓彍鍗曞厓绱犺繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse銆�
	 */
	private boolean shouldScrollToPrevious() {
		return xUp - xDown > switcherViewWidth / 2 || getScrollVelocity() > SNAP_VELOCITY;
	}

	/**
	 * 鍒锋柊鏍囩鍏冪礌甯冨眬锛屾瘡娆urrentItemIndex鍊兼敼鍙樼殑鏃跺�欓兘搴旇杩涜鍒锋柊銆�
	 */
	private void refreshDotsLayout() {
		dotsLayout.removeAllViews();
		for (int i = 0; i < itemsCount; i++) {
			LinearLayout.LayoutParams linearParams = new LinearLayout.LayoutParams(0,
					LayoutParams.FILL_PARENT);
			linearParams.weight = 1;
			RelativeLayout relativeLayout = new RelativeLayout(getContext());
			ImageView image = new ImageView(getContext());
			if (i == currentItemIndex) {
				image.setBackgroundResource(R.drawable.dot_selected);
			} else {
				image.setBackgroundResource(R.drawable.dot_unselected);
			}
			RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
					LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			relativeParams.addRule(RelativeLayout.CENTER_IN_PARENT);
			relativeLayout.addView(image, relativeParams);
			dotsLayout.addView(relativeLayout, linearParams);
		}
	}

	/**
	 * 鍒涘缓VelocityTracker瀵硅薄锛屽苟灏嗚Е鎽镐簨浠跺姞鍏ュ埌VelocityTracker褰撲腑銆�
	 * 
	 * @param event
	 *            鍙充晶甯冨眬鐩戝惉鎺т欢鐨勬粦鍔ㄤ簨浠�
	 */
	private void createVelocityTracker(MotionEvent event) {
		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(event);
	}

	/**
	 * 鑾峰彇鎵嬫寚鍦ㄥ彸渚у竷灞�鐨勭洃鍚琕iew涓婄殑婊戝姩閫熷害銆�
	 * 
	 * @return 婊戝姩閫熷害锛屼互姣忕閽熺Щ鍔ㄤ簡澶氬皯鍍忕礌鍊间负鍗曚綅銆�
	 */
	private int getScrollVelocity() {
		mVelocityTracker.computeCurrentVelocity(1000);
		int velocity = (int) mVelocityTracker.getXVelocity();
		return Math.abs(velocity);
	}

	/**
	 * 鍥炴敹VelocityTracker瀵硅薄銆�
	 */
	private void recycleVelocityTracker() {
		mVelocityTracker.recycle();
		mVelocityTracker = null;
	}

	/**
	 * 妫�娴嬭彍鍗曟粴鍔ㄦ椂锛屾槸鍚︽湁绌胯秺border锛宐order鐨勫�奸兘瀛樺偍鍦▄@link #borders}涓��
	 * 
	 * @param leftMargin
	 *            绗竴涓厓绱犵殑宸﹀亸绉诲��
	 * @param speed
	 *            婊氬姩鐨勯�熷害锛屾鏁拌鏄庡悜鍙虫粴鍔紝璐熸暟璇存槑鍚戝乏婊氬姩銆�
	 * @return 绌胯秺浠讳綍涓�涓猙order浜嗚繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse銆�
	 */
	private boolean isCrossBorder(int leftMargin, int speed) {
		for (int border : borders) {
			if (speed > 0) {
				if (leftMargin >= border && leftMargin - speed < border) {
					return true;
				}
			} else {
				if (leftMargin <= border && leftMargin - speed > border) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 鎵惧埌绂诲綋鍓嶇殑leftMargin鏈�杩戠殑涓�涓猙order鍊笺��
	 * 
	 * @param leftMargin
	 *            绗竴涓厓绱犵殑宸﹀亸绉诲��
	 * @return 绂诲綋鍓嶇殑leftMargin鏈�杩戠殑涓�涓猙order鍊笺��
	 */
	private int findClosestBorder(int leftMargin) {
		int absLeftMargin = Math.abs(leftMargin);
		int closestBorder = borders[0];
		int closestMargin = Math.abs(Math.abs(closestBorder) - absLeftMargin);
		for (int border : borders) {
			int margin = Math.abs(Math.abs(border) - absLeftMargin);
			if (margin < closestMargin) {
				closestBorder = border;
				closestMargin = margin;
			}
		}
		return closestBorder;
	}

	class ScrollTask extends AsyncTask<Integer, Integer, Integer> {

		@Override
		protected Integer doInBackground(Integer... speed) {
			int leftMargin = firstItemParams.leftMargin;
			// 鏍规嵁浼犲叆鐨勯�熷害鏉ユ粴鍔ㄧ晫闈紝褰撴粴鍔ㄧ┛瓒奲order鏃讹紝璺冲嚭寰幆銆�
			while (true) {
				leftMargin = leftMargin + speed[0];
				if (isCrossBorder(leftMargin, speed[0])) {
					leftMargin = findClosestBorder(leftMargin);
					break;
				}
				publishProgress(leftMargin);
				// 涓轰簡瑕佹湁婊氬姩鏁堟灉浜х敓锛屾瘡娆″惊鐜娇绾跨▼鐫＄湢10姣锛岃繖鏍疯倝鐪兼墠鑳藉鐪嬪埌婊氬姩鍔ㄧ敾銆�
				//sleep(10);
			}
			return leftMargin;
		}

		@Override
		protected void onProgressUpdate(Integer... leftMargin) {
			firstItemParams.leftMargin = leftMargin[0];
			firstItem.setLayoutParams(firstItemParams);
		}

		@Override
		protected void onPostExecute(Integer leftMargin) {
			firstItemParams.leftMargin = leftMargin;
			firstItem.setLayoutParams(firstItemParams);
		}
	}

	/**
	 * 浣垮綋鍓嶇嚎绋嬬潯鐪犳寚瀹氱殑姣鏁般��
	 * 
	 * @param millis
	 *            鎸囧畾褰撳墠绾跨▼鐫＄湢澶氫箙锛屼互姣涓哄崟浣�
	 */
	private void sleep(long millis) {
		try {
			Thread.sleep(millis);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

